#include "raylib.h"
#include <string>
#include <algorithm> // For std::min/max
#include <cmath>     // For fabs
#include <iomanip>   // For std::fixed, std::setprecision
#include <sstream>   // For formatting float to string

//----------------------------------------------------------------------------------
// Types and Structures Definition
//----------------------------------------------------------------------------------
typedef struct Car {
    Rectangle rect;
    Color color;
    int mass;           // 整数质量
    int force;          // 整数驱动力
    float acceleration;
    float velocity;
    // rect.x is used for position
    double raceInternalStartTime; // 记录赛车开始移动的精确时间点(绿灯亮起时)
    double finishDurationSeconds; // 完成比赛所用时间
    float finalVelocity;
    bool hasFinishedRace;
    char name[16];
} Car;

typedef enum GameState {
    STATE_SETUP,
    STATE_READY,
    STATE_RACING,
    STATE_FINISHED
} GameState;

//----------------------------------------------------------------------------------
// Global Variables Definition
//----------------------------------------------------------------------------------
const int SCREEN_WIDTH = 1000;
const int SCREEN_HEIGHT = 600;

Car car1;
Car car2;
GameState currentGameState = STATE_SETUP;

const float CAR_WIDTH = 80.0f;
const float CAR_HEIGHT = 40.0f;
const float START_LINE_X = 150.0f;
const float FINISH_LINE_X = SCREEN_WIDTH - 150.0f;
const float TRACK_Y_CAR1 = SCREEN_HEIGHT / 2.0f - CAR_HEIGHT - 20.0f;
const float TRACK_Y_CAR2 = SCREEN_HEIGHT / 2.0f + 20.0f;

// Countdown light
float countdownTimer = 0.0f;
const float RED_LIGHT_DURATION = 1.0f;
const float YELLOW_LIGHT_DURATION = 1.0f;
// Green light means race starts
Color trafficLightColor = RED;

char winnerText[128] = { 0 };
bool car1Winner = false;
bool gameIsPaused = false;
float currentGameTime = 0.0f; // <--- 新增：全局比赛时间 (从绿灯亮起开始计时)

//----------------------------------------------------------------------------------
// Module Functions Declaration
//----------------------------------------------------------------------------------
static void InitGame(void);         // Initialize game
static void UpdateGame(void);       // Update game (one frame)
static void DrawGame(void);         // Draw game (one frame)
static void HandleInput(void);      // Handle user input
static void UpdatePhysics(Car *car, float deltaTime); // Update car physics
static std::string FormatFloat(float value, int precision); // Helper to format float
bool AreColorsEqual(Color c1, Color c2); // <--- 新增声明

//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void) {
    InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Newton's Second Law - Drag Race");
    InitGame();
    SetTargetFPS(60);

    while (!WindowShouldClose()) {
        HandleInput();
        UpdateGame();
        DrawGame();
    }

    CloseWindow();
    return 0;
}

//----------------------------------------------------------------------------------
// Module Functions Definition
//----------------------------------------------------------------------------------
static std::string FormatFloat(float value, int precision) {
    std::stringstream ss;
    ss << std::fixed << std::setprecision(precision) << value;
    return ss.str();
}

void InitGame(void) {
    // Initialize Car 1
    TextCopy(car1.name, "Car 1 (Red)");
    car1.rect = (Rectangle){ START_LINE_X - CAR_WIDTH, TRACK_Y_CAR1, CAR_WIDTH, CAR_HEIGHT };
    car1.color = RED;
    car1.mass = 10; // Default mass (kg or abstract unit)
    car1.force = 50; // Default force (N or abstract unit)
    car1.acceleration = 0.0f;
    car1.velocity = 0.0f;
    car1.hasFinishedRace = false;
    car1.finishDurationSeconds = 0.0;
    car1.finalVelocity = 0.0f;

    // Initialize Car 2
    TextCopy(car2.name, "Car 2 (Blue)");
    car2.rect = (Rectangle){ START_LINE_X - CAR_WIDTH, TRACK_Y_CAR2, CAR_WIDTH, CAR_HEIGHT };
    car2.color = BLUE;
    car2.mass = 10;
    car2.force = 50;
    car2.acceleration = 0.0f;
    car2.velocity = 0.0f;
    car2.hasFinishedRace = false;
    car2.finishDurationSeconds = 0.0;
    car2.finalVelocity = 0.0f;

    currentGameState = STATE_SETUP;
    countdownTimer = 0.0f;
    trafficLightColor = RED;
    winnerText[0] = '\0';
    gameIsPaused = false;
    currentGameTime = 0.0f; // <--- 新增：重置比赛时间
}

void HandleInput(void) {
    if (IsKeyPressed(KEY_P)) {
        if (currentGameState == STATE_RACING || currentGameState == STATE_READY) {
            gameIsPaused = !gameIsPaused;
        }
    }

    if (gameIsPaused) return; // 如果游戏暂停，不处理其他输入（除了取消暂停）

    if (currentGameState == STATE_SETUP) {
        // Car 1 Controls
        if (IsKeyPressed(KEY_W)) car1.force += 5;
        if (IsKeyPressed(KEY_S)) car1.force = std::max(0, car1.force - 5);
        if (IsKeyPressed(KEY_D)) car1.mass += 1;
        if (IsKeyPressed(KEY_A)) car1.mass = std::max(1, car1.mass - 1); // Mass must be at least 1

        // Car 2 Controls
        if (IsKeyPressed(KEY_UP)) car2.force += 5;
        if (IsKeyPressed(KEY_DOWN)) car2.force = std::max(0, car2.force - 5);
        if (IsKeyPressed(KEY_RIGHT)) car2.mass += 1;
        if (IsKeyPressed(KEY_LEFT)) car2.mass = std::max(1, car2.mass - 1);

        if (IsKeyPressed(KEY_SPACE)) {
            currentGameState = STATE_READY;
            countdownTimer = 0.0f;
            trafficLightColor = RED;
        }
    } else if (currentGameState == STATE_FINISHED) {
        if (IsKeyPressed(KEY_SPACE)) {
            InitGame(); // Reset the game
        }
    }
}

void UpdatePhysics(Car *car, float deltaTime) {
    if (car->mass > 0) {
        car->acceleration = (float)car->force / (float)car->mass;
    } else {
        car->acceleration = 0.0f;
    }
    car->velocity += car->acceleration * deltaTime * 10.0f; // Multiply by a factor to make movement more visible
    if (car->velocity < 0) car->velocity = 0; // No reverse
    car->rect.x += car->velocity * deltaTime;
}

void UpdateGame(void) {
    float dt = GetFrameTime();
    double absoluteTime = GetTime(); // 用于计算完成比赛的绝对时间点

    if (gameIsPaused && (currentGameState == STATE_RACING || currentGameState == STATE_READY)) {
        return;
    }


    switch (currentGameState) {
        case STATE_SETUP:
            // Input handled in HandleInput()
            // Ensure cars are at start
            car1.rect.x = START_LINE_X - CAR_WIDTH;
            car1.velocity = 0; car1.acceleration = 0;
            car2.rect.x = START_LINE_X - CAR_WIDTH;
            car2.velocity = 0; car2.acceleration = 0;
            currentGameTime = 0.0f; // 确保在设置阶段时间为0
            break;
        case STATE_READY:
            countdownTimer += dt;
            if (countdownTimer < RED_LIGHT_DURATION) {
                trafficLightColor = RED;
            } else if (countdownTimer < RED_LIGHT_DURATION + YELLOW_LIGHT_DURATION) {
                trafficLightColor = YELLOW;
            } else {
                trafficLightColor = GREEN;
                currentGameState = STATE_RACING;
                double raceStartTime = GetTime();
                car1.raceInternalStartTime = raceStartTime;
                car2.raceInternalStartTime = raceStartTime;
                currentGameTime = 0.0f; // 绿灯亮起，比赛时间开始从0计时
            }
            break;
        case STATE_RACING:
            if (!gameIsPaused) { // 只有在非暂停状态下才更新物理和比赛时间
                if (!car1.hasFinishedRace) UpdatePhysics(&car1, dt);
                if (!car2.hasFinishedRace) UpdatePhysics(&car2, dt);
                currentGameTime += dt; // 累加比赛进行时间
            }

            // 检查车辆是否完成比赛
            if (!car1.hasFinishedRace && (car1.rect.x + car1.rect.width >= FINISH_LINE_X)) {
                car1.hasFinishedRace = true;
                car1.rect.x = FINISH_LINE_X - car1.rect.width; // 精确停在终点线
                car1.finishDurationSeconds = absoluteTime - car1.raceInternalStartTime;
                car1.finalVelocity = car1.velocity;
            }

            if (!car2.hasFinishedRace && (car2.rect.x + car2.rect.width >= FINISH_LINE_X)) {
                car2.hasFinishedRace = true;
                car2.rect.x = FINISH_LINE_X - car2.rect.width; // 精确停在终点线
                car2.finishDurationSeconds = absoluteTime - car2.raceInternalStartTime;
                car2.finalVelocity = car2.velocity;
            }

            // 当两辆车都完成比赛后，才切换到结束状态并宣布胜利者
            if (car1.hasFinishedRace && car2.hasFinishedRace) {
                currentGameState = STATE_FINISHED;
                if (fabs(car1.finishDurationSeconds - car2.finishDurationSeconds) < 0.001) { // 时间非常接近，视为平局
                    TextCopy(winnerText, "It's a TIE!");
                    // car1Winner 对于平局时的颜色显示不重要，可以保持默认或任一值
                } else if (car1.finishDurationSeconds < car2.finishDurationSeconds) {
                    car1Winner = true;
                    TextCopy(winnerText, TextFormat("%s Wins!", car1.name));
                } else {
                    car1Winner = false;
                    TextCopy(winnerText, TextFormat("%s Wins!", car2.name));
                }
            }
            break;
        case STATE_FINISHED:
            // 游戏暂停, 等待空格键重新开始 (在 HandleInput 中处理)
            break;
    }
}

void DrawGame(void) {
    BeginDrawing();
    ClearBackground(RAYWHITE);

    // Draw Track
    DrawLine(START_LINE_X, 50, START_LINE_X, SCREEN_HEIGHT - 50, LIGHTGRAY);
    DrawText("START", START_LINE_X - MeasureText("START", 20)/2, 30, 20, DARKGRAY);
    DrawLine(FINISH_LINE_X, 50, FINISH_LINE_X, SCREEN_HEIGHT - 50, DARKGREEN);
    DrawText("FINISH", FINISH_LINE_X - MeasureText("FINISH", 20)/2, 30, 20, DARKGREEN);

    // Draw Cars
    DrawRectangleRec(car1.rect, car1.color);
    DrawRectangleRec(car2.rect, car2.color);

    // Draw Traffic Light & Global Time
    int lightY = 30;
    int firstLightCenterX = SCREEN_WIDTH / 2 - 80; // 调整灯光组的X起始位置以便为时间腾出空间
    DrawCircle(firstLightCenterX, lightY, 15, (AreColorsEqual(trafficLightColor, RED) && (currentGameState == STATE_READY || currentGameState == STATE_SETUP)) ? RED : Fade(RED, 0.3f));
    DrawCircle(firstLightCenterX + 40, lightY, 15, (AreColorsEqual(trafficLightColor, YELLOW) && currentGameState == STATE_READY) ? YELLOW : Fade(YELLOW, 0.3f));
    DrawCircle(firstLightCenterX + 80, lightY, 15, (AreColorsEqual(trafficLightColor, GREEN) && currentGameState == STATE_RACING) ? GREEN : Fade(GREEN, 0.3f));
    
    // 显示全局比赛时间
    if (currentGameState == STATE_RACING || currentGameState == STATE_READY || currentGameState == STATE_FINISHED) {
         DrawText(TextFormat("Race Time: %s s", FormatFloat(currentGameTime, 2).c_str()), firstLightCenterX + 120, lightY - 8, 20, BLACK);
    }


    // Draw Car Info
    int infoY = 80;
    // Car 1 Info
    DrawText(car1.name, 20, infoY, 20, car1.color);
    DrawText(TextFormat("F: %d N", car1.force), 20, infoY + 25, 18, DARKGRAY);
    DrawText(TextFormat("m: %d kg", car1.mass), 20, infoY + 45, 18, DARKGRAY);
    float effectiveAccel1 = (car1.mass > 0) ? (float)car1.force / car1.mass : 0.0f;
    DrawText(TextFormat("a: %s m/s^2", FormatFloat(effectiveAccel1, 2).c_str()), 20, infoY + 65, 18, DARKGRAY);
    DrawText(TextFormat("V: %s m/s", FormatFloat(car1.velocity, 1).c_str()), 20, infoY + 85, 18, DARKGRAY);
    float displacement1 = (car1.rect.x > (START_LINE_X - CAR_WIDTH)) ? (car1.rect.x - (START_LINE_X - CAR_WIDTH)) : 0.0f;
    DrawText(TextFormat("D: %s m", FormatFloat(displacement1, 1).c_str()), 20, infoY + 105, 18, DARKGRAY);
    if (car1.hasFinishedRace) {
        DrawText(TextFormat("Time: %s s", FormatFloat(car1.finishDurationSeconds, 2).c_str()), 20, infoY + 125, 18, DARKGREEN);
    }

    // Car 2 Info
    DrawText(car2.name, SCREEN_WIDTH - 220, infoY, 20, car2.color);
    DrawText(TextFormat("F: %d N", car2.force), SCREEN_WIDTH - 220, infoY + 25, 18, DARKGRAY);
    DrawText(TextFormat("m: %d kg", car2.mass), SCREEN_WIDTH - 220, infoY + 45, 18, DARKGRAY);
    float effectiveAccel2 = (car2.mass > 0) ? (float)car2.force / car2.mass : 0.0f;
    DrawText(TextFormat("a: %s m/s^2", FormatFloat(effectiveAccel2, 2).c_str()), SCREEN_WIDTH - 220, infoY + 65, 18, DARKGRAY);
    DrawText(TextFormat("V: %s m/s", FormatFloat(car2.velocity, 1).c_str()), SCREEN_WIDTH - 220, infoY + 85, 18, DARKGRAY);
    float displacement2 = (car2.rect.x > (START_LINE_X - CAR_WIDTH)) ? (car2.rect.x - (START_LINE_X - CAR_WIDTH)) : 0.0f;
    DrawText(TextFormat("D: %s m", FormatFloat(displacement2, 1).c_str()), SCREEN_WIDTH - 220, infoY + 105, 18, DARKGRAY);
    if (car2.hasFinishedRace) {
        DrawText(TextFormat("Time: %s s", FormatFloat(car2.finishDurationSeconds, 2).c_str()), SCREEN_WIDTH - 220, infoY + 125, 18, DARKGREEN);
    }

    // Draw Instructions & State
    int bottomTextY = SCREEN_HEIGHT - 100;
    if (currentGameState == STATE_SETUP) {
        DrawText("ADJUST F & m, then PRESS SPACE TO START", SCREEN_WIDTH/2 - MeasureText("ADJUST F & m, then PRESS SPACE TO START", 20)/2, bottomTextY, 20, DARKGRAY);
        DrawText("Car 1 (Red): F (W/S), m (A/D)", 20, SCREEN_HEIGHT - 60, 18, DARKGRAY);
        DrawText("Car 2 (Blue): F (Up/Down), m (Left/Right)", 20, SCREEN_HEIGHT - 35, 18, DARKGRAY);
    } else if (currentGameState == STATE_READY) {
        DrawText("GET READY...", SCREEN_WIDTH/2 - MeasureText("GET READY...", 30)/2, SCREEN_HEIGHT/2, 30, DARKGRAY);
    } else if (currentGameState == STATE_RACING) {
        DrawText("RACING!", SCREEN_WIDTH/2 - MeasureText("RACING!", 30)/2, SCREEN_HEIGHT - 60, 30, DARKGREEN);
    } else if (currentGameState == STATE_FINISHED) {
        DrawText(winnerText, SCREEN_WIDTH/2 - MeasureText(winnerText, 30)/2, SCREEN_HEIGHT/2 - 40, 30, (car1Winner ? car1.color : car2.color)); // 使用 car1Winner 决定颜色
        DrawText(TextFormat("Car 1 Final V: %s m/s, Time: %s s", FormatFloat(car1.finalVelocity,1).c_str(), FormatFloat(car1.finishDurationSeconds,2).c_str()),
                 SCREEN_WIDTH/2 - MeasureText("Car 1 Final V: XXX m/s, Time: XX.XX s", 20)/2, SCREEN_HEIGHT/2 + 0, 20, DARKGRAY);
        DrawText(TextFormat("Car 2 Final V: %s m/s, Time: %s s", FormatFloat(car2.finalVelocity,1).c_str(), FormatFloat(car2.finishDurationSeconds,2).c_str()),
                 SCREEN_WIDTH/2 - MeasureText("Car 2 Final V: XXX m/s, Time: XX.XX s", 20)/2, SCREEN_HEIGHT/2 + 30, 20, DARKGRAY);
        DrawText("PRESS SPACE TO RESTART", SCREEN_WIDTH/2 - MeasureText("PRESS SPACE TO RESTART", 20)/2, SCREEN_HEIGHT - 60, 20, DARKGRAY);
    }

    if (gameIsPaused && (currentGameState == STATE_RACING || currentGameState == STATE_READY)) {
        DrawText("PAUSED", SCREEN_WIDTH / 2 - MeasureText("PAUSED", 40) / 2, SCREEN_HEIGHT / 2 - 20, 40, GRAY);
    }

    EndDrawing();
}

// Helper function for comparing Raylib Colors
bool AreColorsEqual(Color c1, Color c2) {
    return (c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a);
}